/*
 * @Author: xiaosihan
 * @Date: 2023-02-06 15:22:57
 * @Last Modified by: xiehangyun
 * @Last Modified time: 2025-07-24 21:11:24
 */
import hashHistory from '@/srcWeb/hashHistory';
import { AdditiveBlending, AmbientLight, BoxGeometry, DirectionalLight, DoubleSide, Euler, Mesh, MeshLambertMaterial, MeshPhongMaterial, MeshStandardMaterial, PointLight, Vector3, WebGLRenderer } from 'three';
import ThreeBase from 'three-base';
import KeyFrameAnimation from 'three-base/KeyFrameAnimation';
import PlaneModal1 from 'three-base/PlaneModal1';
import SpriteModal1 from 'three-base/SpriteModal1';
import Text3D from 'three-base/Text3D';
import threeUtils from 'three-base/threeUtils';
import Transition from 'three-base/Transition';
import { degToRad } from 'three/src/math/MathUtils';
import GLTF from './component3d/GLTF/GLTF';
import road1PNG from './img/road1.png';

import ExtrudeMesh from 'three-base/ExtrudeMesh';
import Fire from 'three-base/Fire/Fire';
import PlaneWithHtml from 'three-base/PlaneWithHtml';
import Sky from 'three-base/Sky/Sky';
import SpriteText2 from 'three-base/SpriteText2';
import SpriteWithHtml from 'three-base/SpriteWithHtml';
import threeLoader from 'three-base/threeLoader';
import uvJPG from './img/uv.jpg';
import designPNG from './img/design.png';
import aoMapJPG from './img/aoMap.jpeg';
import aoMap2JPG from './img/aoMap2.png';

import InstancedMeshBase from 'three-base/InstancedMeshBase';
import bottleGLB from "./glb/bottle.glb?url";


/**
 *
 *
 * @class HomeRender
 * @extends {ThreeBase}
 */
class HomeRender extends ThreeBase {
    constructor() {
        super();
    }

    // 环境光
    ambientLight = (() => {
        const ambientLight = new AmbientLight('#fff', 1.5);
        this.scene.add(ambientLight);
        return ambientLight;
    })();

    //点光源
    pointLight = (() => {
        const pointLight = new PointLight('#fff', 1.5);
        pointLight.position.set(50, 40, 50);
        pointLight.shadow.bias = -0.001;
        this.scene.add(pointLight);
        return pointLight;
    })();

    // 方向光
    directionalLight = (() => {
        const directionalLight = new DirectionalLight('#fff', 1.5);
        directionalLight.position.set(-10, 10, 5);
        directionalLight.target.position.set(0, 0, 0);
        directionalLight.castShadow = true;
        directionalLight.shadow.bias = -0.001;
        directionalLight.shadow.mapSize.set(1024, 1024);
        this.scene.add(directionalLight);
        return directionalLight;
    })();

    init() {
        super.init();

        // 开发模式时还原记录的位置
        if (threeUtils.isDev && localStorage.lookAt) {
            this.resetLookAt({
                ...JSON.parse(localStorage.lookAt),
            });
        }

        // 开发模式时记录当前的位置
        if (threeUtils.isDev) {
            this.controls.addEventListener('change', () => {
                localStorage.lookAt = JSON.stringify(this.getLookAt());
            });
        }

        if (threeUtils.isProd || (threeUtils.isDev && !localStorage.lookAt)) {
            this.resetLookAt({
                center: new Vector3(0, 0, 0),
                position: new Vector3(-7.049, 27.469, 59.276),
            });
        }
    }

    //火焰
    fire = (() => {
        const fire = new Fire();
        fire.position.set(10, 0, 10);
        this.scene.add(fire);
        return fire;
    })();

    // 发光测试
    glow_test = (() => {
        const glow_test = new Text3D('辉光测试');
        glow_test.scale.set(2, 2, 2);
        glow_test.position.set(-10, 8, 0);

        glow_test.userData = {
            glow_enable: true, //启用发光
            glow_color: '#04fa12', //发光颜色
            glow_width: 1, //发光厚度(像素)
        };

        this.scene.add(glow_test);
        return glow_test;
    })();

    // 描边测试
    stroke_test = (() => {
        const glow_test = new Text3D('描边测试');
        glow_test.scale.set(2, 2, 2);
        glow_test.position.set(-10, 5, 0);

        glow_test.userData = {
            stroke_enable: true, //启用描边
            stroke_color: '#04fa12', //描边颜色
            stroke_width: 4, //描边厚度(像素)
        };

        this.scene.add(glow_test);
        return glow_test;
    })();

    //一个立方体
    box = (() => {
        // 使用高细分度的立方体几何体，以便更好地展示置换效果
        // 参数分别是：宽度、高度、深度、宽度分段数、高度分段数、深度分段数
        const geometry = new BoxGeometry(5, 5, 5, 1, 1, 1);
        const matearil = new MeshStandardMaterial({
            color: '#ffffff',
            // 颜色贴图
            map: threeLoader.getTexture(designPNG),
            aoMap: threeLoader.getTexture(aoMap2JPG),
            aoMapIntensity: 1,
            displacementMap: threeLoader.getTexture(designPNG), // 使用颜色贴图作为置换贴图（注意：这里需要是灰度图，如果是彩色图，Three.js会自动转换为灰度）
            displacementScale: 1, // 调整这个值来控制置换的强度，对于毛绒效果，这个值应该很小
        });
        const mesh = new Mesh(geometry, matearil);

        const transition = new Transition({ rotationY: 0, y: 0 });

        // 动画对象播放回调
        transition.onChange(({ rotationY, y }) => {
            mesh.rotation.y = rotationY;
            mesh.position.setY(y);
            this.needRender = true;
        });

        mesh.position.set(-10, 0, 0);
        mesh.userData = {
            cursor: 'pointer',
            enableEvent: true,
            glow_enable: false, //启用发光
            glow_color: '#04fa12', //发光颜色
            glow_width: 1, //发光厚度(像素)

            bloom_enable: false, //启用发光
            bloom_color: '#04fa12', //发光颜色
            bloom_width: 1, //发光厚度(像素)

        };

        // 点击设置动画对象的值
        mesh.addEventListener('click', (e) => { });

        mesh.addEventListener('dbclick', (e) => {
            console.log('dbclick');
        });

        mesh.addEventListener('leftclick', (e) => {
            transition.set({
                rotationY: Math.random() * 5,
                y: Math.random() * 5,
            });
        });
        mesh.addEventListener('rightclick', (e) => {
            hashHistory.push('/home2');
        });
        // 鼠标移入就发光
        mesh.addEventListener('mouseenter', (e) => {
            // mesh.userData.bloom_enable = true; //启用发光
        });

        // 鼠标离开就不发光
        mesh.addEventListener('mouseleave', (e) => {
            // mesh.userData.bloom_enable = false; //启用发光
        });
        mesh.addEventListener('mousemove', (e) => { });
        mesh.addEventListener('mousedown', (e) => { });
        mesh.addEventListener('mouseup', (e) => { });

        // 使用键盘修改模型的位置
        // keyContorls.addEventListener("change", e => {
        //     mesh.position.add(e.direction);
        //     console.log(mesh.position.toArray().join(" ,"));
        // });

        this.scene.add(mesh);
        return mesh;
    })();

    //天空
    sky = (() => {
        const sky = new Sky();
        this.scene.add(sky);
        return sky;
    })();

    // 加载 gltf
    gltf = (() => {
        const gltf = new GLTF();
        gltf.scale.set(10, 10, 10);
        gltf.position.set(20, 0, 0);
        this.scene.add(gltf);
        return gltf;
    })();

    //关键帧动画对象测试
    keyFrameAnimation = (() => {
        // 创建一个立方体
        const geometry = new BoxGeometry(5, 1, 5);
        const matearil = new MeshLambertMaterial({ color: '#f0f', wireframe: true });
        const mesh = new Mesh(geometry, matearil);

        //创建关键帧动画对象
        const keyFrameAnimation = new KeyFrameAnimation({
            object3d: mesh,
            keyframes: [
                { position: new Vector3(0, 0, 0), scale: new Vector3(1, 1, 1), rotation: new Euler(0, 0, 0), timeTemp: 0 },
                { position: new Vector3(0, 5, 1), scale: new Vector3(1, 1, 1), rotation: new Euler(0, degToRad(0), 0), timeTemp: 5000 },
                { position: new Vector3(0, 5, 5), scale: new Vector3(1, 1, 1), rotation: new Euler(0, degToRad(0), 0), timeTemp: 10000 },
            ],
        });

        // 当前
        keyFrameAnimation.addEventListener('update', () => {
            this.needRender = true;
        });

        this.scene.add(keyFrameAnimation);

        return keyFrameAnimation;
    })();

    //3D组件提示窗
    spriteModal1 = (() => {
        const spriteModal1 = new SpriteModal1();
        // 更新文本
        spriteModal1.updata({
            size: 10,
            title: 'SpriteModal1',
            titleColor: '#ffffff',
            texts: [{ text: '3D组件提示窗 SpriteModal1' }, { text: '支持鼠标事件,自动换行,文字颜色,文字大小', color: '#ffff00' }, { text: '使用\\n换行', color: '#00ffff' }],
        });
        spriteModal1.userData = { cursor: 'pointer', enableEvent: true };
        spriteModal1.addEventListener('leftclick', (e) => { });
        spriteModal1.position.set(-20, 0, 0);
        this.scene.add(spriteModal1);
        return spriteModal1;
    })();

    //3D平面组件提示窗
    planeModal1 = (() => {
        const planeModal1 = new PlaneModal1();
        // 更新文本
        planeModal1.updata({
            size: 10,
            title: 'PlaneModal1',
            titleColor: '#ffffff',
            texts: [{ text: '3D平面组件弹窗 PlaneModal1' }, { text: '支持鼠标事件,自动换行,文字颜色,文字大小', color: '#ffff00' }, { text: '使用\\n换行', color: '#00ffff' }],
        });
        planeModal1.userData = { cursor: 'pointer', enableEvent: true };
        planeModal1.addEventListener('leftclick', (e) => { });
        planeModal1.position.set(-30, 0, 0);
        this.scene.add(planeModal1);
        return planeModal1;
    })();

    // 3D文字
    text3D = (() => {
        const text3D = new Text3D('new Text3D\n3d文字组件');
        text3D.position.set(6, 2, 0);
        this.scene.add(text3D);
        return text3D;
    })();

    // htlml样式面板
    planeWithHtml = (() => {
        const planeWithHtml = new PlaneWithHtml(`
            <span style="font-family: 黑体;font-size:100px;color:#000;" >PlaneWithHtml</span>
            <br/>
            <span style="font-family: 黑体;font-size:100px;color:#f00;" >htlml文字组件</span>
        `);
        planeWithHtml.position.set(6, 6, 0);
        planeWithHtml.scale.set(0.01, 0.01, 0.01);
        planeWithHtml.rotateX(degToRad(90));

        //three事件
        planeWithHtml.userData = { cursor: 'pointer', enableEvent: true };
        planeWithHtml.addEventListener('leftclick', (e) => { });

        this.scene.add(planeWithHtml);
        return planeWithHtml;
    })();

    // htlml样式面板
    spriteWithHtml = (() => {
        const spriteWithHtml = new SpriteWithHtml();

        spriteWithHtml.position.set(6, 9, 0);

        spriteWithHtml
            .setHtml(
                `
            <span style="font-family: 黑体;font-size:100px;color:#000;" >PlaneWithHtml</span>
            <br/>
            <span style="font-family: 黑体;font-size:100px;color:#f00;" >htlml文字组件</span>
        `
            )
            .then(() => {
                spriteWithHtml.scale.multiplyScalar(0.01);
            });

        this.scene.add(spriteWithHtml);
        return spriteWithHtml;
    })();

    // 挤出公路模型
    extrudeMesh = (() => {
        const material = new MeshPhongMaterial({
            side: DoubleSide,
            map: threeLoader.getTexture(road1PNG),
        });
        const extrudeMesh = new ExtrudeMesh(
            {
                paths: [
                    // 挤出路径的点位置    转弯半径   转弯分段数     当前点的缩放            取个名字
                    { vector3: [0, 0, -10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
                    { vector3: [40, 0, -10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
                    { vector3: [40, 0, 10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
                    { vector3: [0, 0, 10], radius: 3, segments: 2, scale: { x: 1, y: 1 }, name: '路口1' },
                ], // 自动生成路径的
                shapePath: [
                    [-2, 0],
                    [2, 0],
                ], // 被拉伸成模型的平面路径
                closed: false, // 是否闭合路径
            },
            material
        );
        this.scene.add(extrudeMesh);
        return extrudeMesh;
    })();

    // 精灵文字样式2
    spriteText2 = (() => {
        const spriteText2 = new SpriteText2('精灵文字2');
        //three事件
        spriteText2.userData = {
            cursor: 'pointer',
            enableEvent: true,
        };
        spriteText2.addEventListener('leftclick', (e) => {
            if (spriteText2.text === '精灵文字2') {
                spriteText2.text = 'SpriteText2';
            } else {
                spriteText2.text = '精灵文字2';
            }
        });

        spriteText2.padding = 1;
        spriteText2.backgroundColor = 'rgba(0,0,0,0.5)';
        spriteText2.borderColor = '#fff000';
        spriteText2.borderWidth = 1;
        spriteText2.borderRadius = 4;
        spriteText2.position.set(0, 15, 0);
        this.scene.add(spriteText2);
        return spriteText2;
    })();

    //加载实例模型的例子,瓷瓶模型
    instancedMeshBase = (() => {
        const instancedMeshBase = new InstancedMeshBase(bottleGLB);
        instancedMeshBase.addEventListener('loaded', () => {
            //设置实例组的长度
            instancedMeshBase.setCount(2);
            // 这个方法可以不用操作矩阵
            instancedMeshBase.setTRS(0, {
                scale: new Vector3(1.2, 1.2, 1.2),
                position: new Vector3(0, 0, 0),
                rotation: new Euler(0, 0, 0),
            });

            instancedMeshBase.setTRS(1, {
                scale: new Vector3(1.5, 1.5, 1.5),
                position: new Vector3(4, 0, 0),
                rotation: new Euler(0, 0, 0),
            });

        });
        this.add(instancedMeshBase);
        return instancedMeshBase;
    })();
}

const homeRenderer = new HomeRender();

export default homeRenderer;
